package com.mhxy.service;

import com.mhxy.constant.ParamConstants;
import com.mhxy.constant.PicConstants;
import com.mhxy.entity.FindPicResult;
import com.mhxy.enums.Coord;
import com.mhxy.handler.TaskProgressHandler;
import com.mhxy.util.*;
import com.sun.jna.platform.win32.WinDef;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

@Slf4j
public abstract class AbstractTask implements TaskInterface {

    protected final WinDef.HWND hwnd_0;
    protected FindPicResult pic;

    // 常量定义
    private static final int DEFAULT_BATTLE_SLEEP = 15000;
    private static final int DEFAULT_RETRY_COUNT = 5;

    public AbstractTask(WinDef.HWND hwnd_0) {
        this.hwnd_0 = hwnd_0;
    }

    @Override
    public abstract Boolean before() throws Exception;

    @Override
    public abstract Boolean execute() throws Exception;

    @Override
    public abstract Boolean after() throws Exception;

    @Override
    public abstract String getTaskName() throws Exception;

    /**
     * 前往"建邺城"
     */
    protected boolean goToJianYe() throws Exception {
        if (!openWorldMap()) {
            return false;
        }

        // 点击地图右滑，确保能找到建邺城
        MouseUtil.lClickRandom(hwnd_0, Coord.MAP_SLIDE.getX(), Coord.MAP_SLIDE.getY());
        FuzzyPicUtil.findAndClickRandom(hwnd_0, PicConstants.公共_建邺城大图标2, DEFAULT_RETRY_COUNT);
        return true;
    }

    /**
     * 前往"长安城"
     */
    protected boolean goToChangAn() throws Exception {
        if (!openWorldMap()) {
            return false;
        }

        // 点击地图右滑，确保能找到长安城
        MouseUtil.lClickRandom(hwnd_0, Coord.MAP_SLIDE.getX(), Coord.MAP_SLIDE.getY());
        pic = FuzzyPicUtil.findPic(hwnd_0, PicConstants.公共_长安城大图标, DEFAULT_RETRY_COUNT);
        MouseUtil.lClickRandom(hwnd_0, 
            pic.getPicX() + Coord.CHANGAN_MAP_DXY.getX(), 
            pic.getPicY() + Coord.CHANGAN_MAP_DXY.getY()
        );

        boolean success = waitForMapIcon(PicConstants.公共_长安城小图标);
        if (success) {
            log.info("返回长安城成功！");
            ThreadUtil.sleep1();
            return true;
        }
        
        log.error("返回长安城失败！");
        return false;
    }

    /**
     * 打开世界地图
     */
    private boolean openWorldMap() throws Exception {
        clickEsc1();
        // 点击主地图(点击两次，保证成功)
        MouseUtil.lClickRandom(hwnd_0, Coord.MAJOR_MAP_XY.getX(), Coord.MAJOR_MAP_XY.getY());
        ThreadUtil.sleep1();
        MouseUtil.lClickRandom(hwnd_0, Coord.MAJOR_MAP_XY.getX(), Coord.MAJOR_MAP_XY.getY());
        return true;
    }

    /**
     * 等待地图图标出现
     */
    private boolean waitForMapIcon(String iconPath) throws Exception {
        return FuzzyPicUtil.findPic(hwnd_0, iconPath, DEFAULT_RETRY_COUNT).isFinded();
    }

    /**
     * 战斗时间
     */
    protected void findBattle() throws Exception {
        findBattle(DEFAULT_BATTLE_SLEEP);
    }

    protected void findBattle(long sleep) throws Exception {
        String[] battleIcons = {PicConstants.公共_战斗中, PicConstants.公共_战斗中2};
        while (FuzzyPicUtil.findPicM(hwnd_0, battleIcons, 1).isFinded()) {
            log.info("【{}】战斗中...", getTaskName());
            ThreadUtil.sleep(sleep);
        }
    }

    /**
     * 找到"日常活动"并打开
     */
    protected boolean findAndClickActivity() throws Exception {
        clickEsc1();
        
        // 找到活动并打开
        if (!clickWithRetry(PicConstants.公共_活动, "活动")) {
            return false;
        }
        
        ThreadUtil.sleep1();
        
        // 找到日常活动并点击
        if (!clickWithRetry(PicConstants.公共_日常活动, "日常活动")) {
            return false;
        }
        
        // 拉到最顶端
        MouseUtil.dragMove(hwnd_0, Coord.ACTIVITY_WHELL.getX(), Coord.ACTIVITY_WHELL.getY(), 0, 1000);
        return true;
    }

    private boolean clickWithRetry(String picPath, String actionName) throws Exception {
        if (!FuzzyPicUtil.findAndClickRandom(hwnd_0, hwnd_0, picPath, DEFAULT_RETRY_COUNT)) {
            log.error("【{}】打开'{}'失败！", getTaskName(), actionName);
            return false;
        }
        return true;
    }

    /**
     * 使用物品
     */
    protected void clickUse(int count) throws Exception {
        for (int i = 0; i < count; i++) {
            FuzzyPicUtil.findAndClickRandom(hwnd_0, PicConstants.公共_使用, 1);
            clickEsc1();
            log.info("【{}】使用物品", getTaskName());
        }
    }

    /**
     * 使用物品关闭
     */
    protected void clickUseClose(int count) throws Exception {
        for (int i = 0; i < count; i++) {
            boolean result = FuzzyPicUtil.findAndClickRandom(hwnd_0, hwnd_0, PicConstants.公共_弹出使用物品关系, 1);
            log.info("【{}】使用物品关闭: {}", getTaskName(), result);
        }
    }

    /**
     * 根据任务LOGO找到任务并参加
     */
    protected Boolean findAndClickTaskLogo(String taskLogoPic, String taskFinishPic) throws Exception {
        return this.findAndClickTaskLogo(taskLogoPic, new String[]{taskFinishPic});
    }
    protected Boolean findAndClickTaskLogo(String taskLogoPic, String[] taskFinishPics) throws Exception {
        for (int i = 0; i < ParamConstants.UNIFY_TIMES; i++) {
            // 判断任务是否已完成
            if (taskFinishPics.length > 0) {
                pic = FuzzyPicUtil.findPicM(hwnd_0, taskFinishPics, 2, 0.95);
                if (pic.getFindResult()[0] == 1 || pic.getFindResult()[1] == 1) {
                    // 摁ESC，退出
                    ThreadUtil.sleep1();
                    clickEsc(1);
                    log.error("【{}】已完成！", getTaskName());
                    TaskProgressHandler.updateProgress(getTaskName(), "完成");
                    return null;
                }
            }
            pic = FuzzyPicUtil.findPic(hwnd_0, taskLogoPic, 2);
            if (pic.isFinded()) {
                log.info("【{}】成功找到任务图标！", getTaskName());
                // 找到图标后 点击右边的"参与"
                MouseUtil.lClickRandom(hwnd_0, pic.getPicX() + Coord.ATTEND_TASK_DXY.getX(), pic.getPicY() + Coord.ATTEND_TASK_DXY.getY());
                return true;
            }
            // 如果没找到下拉滑动屏幕寻找图标
            MouseUtil.dragMove(hwnd_0, Coord.ACTIVITY_WHELL.getX(), Coord.ACTIVITY_WHELL.getY(), 0, -90);
        }
        // 一直没找到，可能任务时间还没开始
        log.error("【{}】一直没找到任务图标, 任务失败！", getTaskName());
        TaskProgressHandler.updateProgress(getTaskName(), "失败");
        return false;
    }

    /**
     * 根据任务标题找到任务并参加
     */
    protected Boolean findAndClickTaskTitle(String taskLogoTitlePic, String taskFinishPic) throws Exception {
        return this.findAndClickTaskTitle(taskLogoTitlePic, new String[]{taskFinishPic});
    }
    protected Boolean findAndClickTaskTitle(String taskLogoTitlePic, String[] taskFinishPics) throws Exception {
        for (int i = 0; i < ParamConstants.UNIFY_TIMES; i++) {
            // 判断任务是否已完成
            if (taskFinishPics.length > 0) {
                pic = FuzzyPicUtil.findPicM(hwnd_0, taskFinishPics, 3, 0.95);
                if (pic.getFindResult()[0] == 1 || pic.getFindResult()[1] == 1) {
                    // 摁ESC，退出
                    ThreadUtil.sleep1();
                    clickEsc(1);
                    log.error("【{}】已完成！", getTaskName());
                    TaskProgressHandler.updateProgress(getTaskName(), "完成");
                    return null;
                }
            }
            pic = FuzzyPicUtil.findPic(hwnd_0, taskLogoTitlePic, 5, 0.8);
            if (pic.isFinded()) {
                log.info("【{}】成功找到任务Title！", getTaskName());
                // 找到图标后 点击右边的"参与"
                MouseUtil.lClickRandom(hwnd_0, pic.getPicX() + Coord.ATTEND_TASK_TITLE_DXY.getX(), pic.getPicY() + Coord.ATTEND_TASK_TITLE_DXY.getY());
                return true;
            }
            // 如果没找到下拉滑动屏幕寻找图标
            MouseUtil.dragMove(hwnd_0, Coord.ACTIVITY_WHELL.getX(), Coord.ACTIVITY_WHELL.getY(), 0, -90);
        }
        // 一直没找到，可能任务时间还没开始
        log.error("【{}】一直没找到任务图标, 任务失败！", getTaskName());
        TaskProgressHandler.updateProgress(getTaskName(), "失败");
        return false;
    }

    /**
     * 查找任务列表，并点击
     */
    protected boolean findAndClickTaskList(String taskListPic) throws Exception {
        // 任务列表如果关闭，则点击打开
        FuzzyPicUtil.findAndClickRandom(hwnd_0, PicConstants.公共_任务列表开关, 1);
        ThreadUtil.sleep1();
        // 下拉任务列表到最顶端
        MouseUtil.dragMove(hwnd_0, Coord.TASK_LIST_WHELL.getX(), Coord.TASK_LIST_WHELL.getY(), 0, 1000);
        ThreadUtil.sleep1();
        // 点击任务图标
        if (FuzzyPicUtil.findAndClickRandom(hwnd_0, taskListPic, 3, 0.7)) {
            log.info("【{}】任务已接，继续战斗！", getTaskName());
            return true;
        }
        return false;
    }

    /**
     * 运行副本
     */
    protected boolean runInstance(List<String> confirmBattlePics) throws Exception {
        while (true) {
            FuzzyPicUtil.findAndClickRandom(hwnd_0, PicConstants.普通副本_跳过剧情动画, 1);
            ThreadUtil.sleep(5000);

            FuzzyPicUtil.findAndClickRandom(hwnd_0, PicConstants.普通副本_战斗时钟, 1);
            ThreadUtil.sleep(5000);

            for (String pic : confirmBattlePics) {
                FuzzyPicUtil.findAndClickRandom(hwnd_0, pic, 1);
            }

            findBattle();

            // 是否已返回 长安城
            if (FuzzyPicUtil.findPic(hwnd_0, PicConstants.公共_长安城小图标, 2).isFinded()) {
                return true;
            }
        }
    }

    protected boolean runInstance() throws Exception {
        while (true) {
            clickEsc3();

            FuzzyPicUtil.findAndClickRandom(hwnd_0, PicConstants.普通副本_跳过剧情动画, 1);
            ThreadUtil.sleep2();

            if (FuzzyPicUtil.findAndClickRandom(hwnd_0, PicConstants.普通副本_战斗时钟, 1)) {
                ThreadUtil.sleep1();
                FuzzyPicUtil.findAndClickRandom(hwnd_0, PicConstants.普通副本_进入战斗, 1);
                ThreadUtil.sleep2();
            }

            findBattle();

            // 是否已返回 长安城
            if (FuzzyPicUtil.findPic(hwnd_0, PicConstants.公共_活动, 1).isFinded()) {
                return true;
            }
        }
    }

    protected void clickEsc1() throws Exception {
        clickEsc(1);
    }

    protected void clickEsc3() throws Exception {
        clickEsc(3);
    }

    protected void clickEsc(int number) throws Exception {
        for (int i = 0; i < number; i++) {
            // 按键无效，使用鼠标右击一下
            MouseUtil.rClickRandom(hwnd_0, Coord.RIGHT_CLICK_XY.getX(), Coord.RIGHT_CLICK_XY.getY());
        }
    }
}
